﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace CloudShot.Core.Utils
{
	/// <summary>
	/// Represents the utility class to resize <see cref="Image"/> by different ways.
	/// </summary>
	/// <remarks>http://www.codeproject.com/KB/GDI-plus/imageresize.aspx</remarks>
	public static class ImgResizer
	{
		/// <summary>
		/// Resizes <paramref name="image"/> to fixed size with base proportions saving.
		/// </summary>
		/// <param name="image">An image to resize.</param>
		/// <param name="width">A final width of the image.</param>
		/// <param name="height">A final height of the image.</param>
		/// <param name="fillColor">A color to fill empty parts of final image.</param>
		/// <param name="interpolationMode">An <see cref="InterpolationMode"/> for final image.</param>
		/// <returns>The resized image.</returns>
		public static Image FixedSize(Image image, int width, int height, Color fillColor, InterpolationMode interpolationMode = InterpolationMode.HighQualityBicubic)
		{
			return Resize(image, width, height, true, fillColor, interpolationMode);
		}

		/// <summary>
		/// Resizes <paramref name="image"/> with base proportions saving.
		/// </summary>
		/// <param name="image">An image to resize.</param>
		/// <param name="width">A final width of the image.</param>
		/// <param name="height">A final height of the image.</param>
		/// <param name="interpolationMode">An <see cref="InterpolationMode"/> for final image.</param>
		/// <returns>The resized image.</returns>
		public static Image Resize(Image image, int width, int height, InterpolationMode interpolationMode = InterpolationMode.HighQualityBicubic)
		{
			return Resize(image, width, height, false, Color.Transparent, interpolationMode);
		}

		/// <summary>
		/// Resizes <paramref name="image"/> to specified size with base proportions saving.
		/// </summary>
		/// <param name="image">An image to resize.</param>
		/// <param name="width">A final width of the image.</param>
		/// <param name="height">A final height of the image.</param>
		/// <param name="fixSize">A <see cref="bool"/> paramener indicates that final image must be fixed size.</param>
		/// <param name="fillColor">A color to fill empty parts of final image.</param>
		/// <param name="interpolationMode">An <see cref="InterpolationMode"/> for final image.</param>
		/// <returns>The resized image.</returns>
		private static Image Resize(Image image, int width, int height, bool fixSize, Color fillColor, InterpolationMode interpolationMode = InterpolationMode.HighQualityBicubic)
		{
			int sourceWidth = image.Width;
			int sourceHeight = image.Height;
			int destX = 0;
			int destY = 0;

			float nPercent = 0;
			float nPercentW = 0;
			float nPercentH = 0;

			nPercentW = (width / (float)sourceWidth);
			nPercentH = (height / (float)sourceHeight);
			nPercent = nPercentH < nPercentW ? nPercentH : nPercentW;

			if (fixSize)
			{
				if (nPercentH < nPercentW)
					destX = Convert.ToInt16((width - (sourceWidth * nPercent)) / 2);
				else
					destY = Convert.ToInt16((height - (sourceHeight * nPercent)) / 2);
			}

			int destWidth = (int)(sourceWidth * nPercent);
			int destHeight = (int)(sourceHeight * nPercent);

			int bmpWidth = fixSize ? width : destWidth;
			int bmpHeight = fixSize ? height : destHeight;
			var bmPhoto = new Bitmap(bmpWidth, bmpHeight, PixelFormat.Format32bppArgb);

			bmPhoto.SetResolution(image.HorizontalResolution, image.VerticalResolution);

			using (Graphics grPhoto = Graphics.FromImage(bmPhoto))
			{
				grPhoto.Clear(fillColor);
				grPhoto.InterpolationMode = interpolationMode;

				grPhoto.DrawImage(image,
						new Rectangle(destX, destY, destWidth, destHeight),
						new Rectangle(0, 0, sourceWidth, sourceHeight),
						GraphicsUnit.Pixel);

				grPhoto.Dispose();
			}

			return bmPhoto;
		}

		/// <summary>
		/// Resizes image to specified size with base proportion saving and creates thumbnail from it using <see cref="Image.GetThumbnailImage"/> method.
		/// </summary>
		/// <param name="image">An image to resize.</param>
		/// <param name="width">A final width of the image.</param>
		/// <param name="height">A final height of the image.</param>
		/// <returns>The resized image.</returns>
		public static Image Thumbnail(Image image, int width, int height)
		{
			double k1 = ((double)width) / image.Width;
			double k2 = ((double)height) / image.Height;
			double k = (k1 > k2) ? k2 : k1;

			int w = (int)(image.Width * k);
			int h = (int)(image.Height * k);

			return image.GetThumbnailImage(w, h, () => false, IntPtr.Zero);
		}
	}
}